package server

import (
	"account/drivers"
	"account/models"
	"encoding/json"
	"strings"
	"sync"

	"github.com/go-redis/redis"
)

const serverNameRedisKey = "account:account:all" // 获取所有的账户信息
// var redisDb *redis.Client = drivers.Client       // 测试使用单节点
var redisDb *redis.ClusterClient = drivers.ClientCluster // 集群节点

// 获取删除的账户数据
// 获取所有父级别数据
func GetAccountBlackAll() ([]*models.Account, error) {

	var accounts []*models.Account
	if result := drivers.SqlClusterDb.Preload("Market").
		Preload("Exchange").
		Where(map[string]interface{}{"deleted": 1, "active": 0}).
		Or(map[string]interface{}{"deleted": 1, "active": 1}).
		Or(map[string]interface{}{"deleted": 0, "active": 0}).
		Or(map[string]interface{}{"deleted": "", "active": ""}).
		Preload("Childs").
		Find(&accounts).GetErrors(); len(result) > 0 {
		return accounts, result[0]
	}
	return accounts, nil
}

// 获取所有父级别数据
func GetAccountAll() ([]*models.Account, error) {

	var accounts []*models.Account
	if result := drivers.SqlClusterDb.Preload("Market").Preload("Exchange").Where(map[string]interface{}{"deleted": 0, "active": 1}).Where("parent_id is null").Preload("Childs").Find(&accounts).GetErrors(); len(result) > 0 {
		return accounts, result[0]
	}
	return accounts, nil
}

// 获取所有账户信息
// 需要注意的是数据字段的类型跟自定义的结构体类型部分会有一些字段冲突
// 冲突情况可以通过Debug SQL 日志来进行分析
func GetAccountAllInfos() ([]*models.Account, error) {

	var accounts_n []*models.Account
	var errors []error
	var wg = &sync.WaitGroup{}

	accounts, err := GetAccountAll()
	if err != nil {
		return accounts, err
	}

	accounts_n = make([]*models.Account, len(accounts))
	for i, account := range accounts {
		// drivers.SqlClusterDb.ModelSlave(&account).Preload("Market").Preload("Exchange").Related(&account.Childs, "childs").Find(&account)
		accounts_n[i] = account
		wg.Add(1)
		go func(account *models.Account, wg *sync.WaitGroup, i int, accounts_n []*models.Account) {
			defer wg.Done()
			err := drivers.SqlClusterDb.ModelSlave(&account).Preload("Market").Preload("Exchange").Related(&account.Childs, "childs").Where(map[string]interface{}{"deleted": 0, "active": 1}).Find(&account).Error
			if err != nil {
				errors = append(errors, err)
			}
			// fmt.Println("执行完成", i)
			accounts_n[i] = account
		}(account, wg, i, accounts_n)
	}

	if len(errors) > 0 {
		return accounts, errors[0]
	}

	wg.Wait()
	return accounts_n, nil
}

// 从Redis中读取缓存信息
func AcquireAccountCacheInfos() (res []map[string]interface{}, err error) {

	result, _ := redisDb.Get(serverNameRedisKey).Result()

	if strings.Compare(result, "") == 0 {
		accounts, err := GetAccountAll()
		if err != nil {
			return res, err
		}
		res, _ := json.Marshal(accounts)
		result = string(res)
	}
	resultB := []byte(result)
	err = json.Unmarshal(resultB, &res)
	return

}

// 获取某一个账户的信息
func FetchAccountOne(id int) (models.Account, error) {

	var accounts models.Account
	if result := drivers.SqlClusterDb.Preload("Market").Preload("Exchange").Where(map[string]interface{}{"deleted": 0, "active": 1, "id": id}).Find(&accounts).GetErrors(); len(result) > 0 {
		return accounts, result[0]
	}

	err := drivers.SqlClusterDb.ModelSlave(&accounts).Preload("Market").Preload("Exchange").Related(&accounts.Childs, "childs").Where(map[string]interface{}{"deleted": 0, "active": 1}).Find(&accounts).Error
	if err != nil {
		return accounts, err
	}
	return accounts, nil
}

// 新增账户信息
func AddAccountInfo(account models.Account) ([]models.Account, error) {

	if err := drivers.SqlClusterDb.Omit("Market", "Exchange").Create(&account).Error; err != nil {
		return nil, err
	}

	var accounts []models.Account
	if result := drivers.SqlClusterDb.Preload("Market").Preload("Exchange").Where("id = ?", account.Id).Find(&accounts).GetErrors(); len(result) > 0 {
		return accounts, result[0]
	}
	return accounts, nil
}

// 更新账户信息
func UpdateAccountInfo(id int, account models.Account) error {

	updateData := map[string]interface{}{
		"name":        account.Name,
		"deleted":     account.Deleted,
		"access_key":  account.AccessKey,
		"secret_key":  account.SecretKey,
		"active":      account.Active,
		"note":        account.Note,
		"level":       account.Level,
		"role":        account.Role,
		"capital":     account.Capital,
		"cur_fund":    account.CurFund,
		"base_fund":   account.BaseFund,
		"reserved":    account.Reserved,
		"market_id":   account.MarketId,
		"exchange_id": account.ExchangeId,
		"parent_id":   account.ParentId,
	}

	if account.ParentId == 0 {
		updateData["parent_id"] = nil
	}

	if err := drivers.SqlClusterDb.MasterTable("account").Where("id = ?", id).Updates(
		updateData).Error; err != nil {
		return err
	}
	return nil
}

// 更新账户信息
func ActiveAccountInfo(id int) error {
	if err := drivers.SqlClusterDb.Model(&models.Account{}).Where("id = ?", id).Update("active", 0).Error; err != nil {
		return err
	}
	return nil
}

// 根据条件获取某个或者某些账户信息
func GetAccountFilterInfos(query interface{}, args ...interface{}) ([]models.Account, error) {
	var accounts []models.Account
	// if result := drivers.SqlClusterDb.Where("parent_id is null").Where(query, args...).Preload("Childs").Find(&accounts).GetErrors(); len(result) > 0 {
	if result := drivers.SqlClusterDb.Where(query, args...).Preload("Childs").Where(map[string]interface{}{"deleted": 0, "active": 1}).Find(&accounts).GetErrors(); len(result) > 0 {
		return accounts, result[0]
	}
	return accounts, nil
}

// 处理队列的过滤条件
func GetAccountFilterQueueInfos() ([]models.Account, error) {
	var accounts []models.Account
	// if result := drivers.SqlClusterDb.Preload("Market").Preload("Exchange").Where("parent_id is null").Find(&accounts).GetErrors(); len(result) > 0 {
	if result := drivers.SqlClusterDb.Preload("Market").Preload("Exchange").Where(map[string]interface{}{"deleted": 0, "active": 1}).Find(&accounts).GetErrors(); len(result) > 0 {

		return accounts, result[0]
	}
	return accounts, nil
}
